package com.sos.core.game
{
	
	import com.sos.core.DataObject;
	import com.sos.logging.Dumper;
	import com.sos.logging.IDumpable;
	
	import flash.utils.Dictionary;
	
	public class GameOptions extends DataObject implements IDumpable
	{
		
		// -------------------------------------------------------------------------------
		// CONSTANTS
		// -------------------------------------------------------------------------------
		
		// JSON Property names
		protected const		JSON_PROPERTY_TURNS:String						= "turns";
		protected const		JSON_PROPERTY_DECK_SIZE:String					= "deckSize";
		protected const		JSON_PROPERTY_HAND_SIZE:String					= "handSize";
		protected const		JSON_PROPERTY_DISCARD_SIZE:String				= "discardSize";
		protected const		JSON_PROPERTY_TIMEOUT_ENABLED:String			= "timeoutEnabled";
		protected const		JSON_PROPERTY_TIMEOUT_PLAY_PHASE:String			= "timeoutPlayPhase";
		protected const		JSON_PROPERTY_TIMEOUT_DISCARD_PHASE:String		= "timeoutDiscardPhase";
		protected const		JSON_PROPERTY_TIMEOUT_SUBSTITUTION_PHASE:String	= "timeoutSubstitutionPhase";
		
		// Default values
		public static const DEFAULT_TURNS:uint								= 20;
		public static const DEFAULT_DECK_SIZE:uint							= 40;
		public static const DEFAULT_HAND_SIZE:uint							= 6;
		public static const DEFAULT_DISCARD_SIZE:uint						= 3;
		public static const DEFAULT_TIMEOUT_ENABLED:Boolean					= false; // ms
		public static const DEFAULT_TIMEOUT_PLAY_PHASE:uint					= 30000; // ms
		public static const DEFAULT_TIMEOUT_DISCARD_PHASE:uint				= 15000; // ms
		public static const DEFAULT_TIMEOUT_SUBSTITUTION_PHASE:uint			= 20000; // ms
		
		// -------------------------------------------------------------------------------
		// FIELDS
		// -------------------------------------------------------------------------------
		
		private var _turns:uint;
		private var _deckSize:uint;
		private var _handSize:uint;
		private var _discardSize:uint;
		private var _timeoutEnabled:Boolean;		// 
		private var _timeoutPlayPhase:uint;			// milliseconds
		private var _timeoutDiscardPhase:uint;		// milliseconds
		private var _timeoutSubstitutionPhase:uint;	// milliseconds
		
		// -------------------------------------------------------------------------------
		// CONSTRUCTOR
		// -------------------------------------------------------------------------------
		
		public function GameOptions(data:Object = null)
		{
			// Clear
			clear();
			// If data is provided, initializes the turn
			if (data != null) load(data);
		}
		
		// -------------------------------------------------------------------------------
		// PROPERTIES
		// -------------------------------------------------------------------------------		

		public function get turns():uint
		{
			return _turns;
		}
		
		public function set turns(value:uint):void
		{
			_turns = value;
		}
		
		public function get turnsForPeriod():uint
		{
			return _turns / 2;
		}
		
		public function get firstTurnOfFirstPeriod():uint
		{
			return 1;
		}
		
		public function get firstTurnOfSecondPeriod():uint
		{
			return firstTurnOfFirstPeriod + turnsForPeriod;
		}
		
		public function get deckSize():uint
		{
			return _deckSize;
		}

		public function set deckSize(value:uint):void
		{
			_deckSize = value;
		}
		
		public function get handSize():uint
		{
			return _handSize;
		}
		
		public function set handSize(value:uint):void
		{
			_handSize = value;
		}
		
		public function get discardSize():uint
		{
			return _discardSize;
		}
		
		public function set discardSize(value:uint):void
		{
			_discardSize = value;
		}

		public function get timeoutEnabled():Boolean
		{
			return _timeoutEnabled;
		}
		
		public function set timeoutEnabled(value:Boolean):void
		{
			_timeoutEnabled = value;
		}
		
		public function get timeoutPlayPhase():uint
		{
			return _timeoutPlayPhase;
		}
		
		public function set timeoutPlayPhase(value:uint):void
		{
			_timeoutPlayPhase = value;
		}
		
		public function get timeoutDiscardPhase():uint
		{
			return _timeoutDiscardPhase;
		}
		
		public function set timeoutDiscardPhase(value:uint):void
		{
			_timeoutDiscardPhase = value;
		}
		
		public function get timeoutSubstitutionPhase():uint
		{
			return _timeoutSubstitutionPhase;
		}
		
		public function set timeoutSubstitutionPhase(value:uint):void
		{
			_timeoutSubstitutionPhase = value;
		}
		
		// -------------------------------------------------------------------------------
		// PRIVATE METHODS
		// -------------------------------------------------------------------------------
		
		override protected function validate(data:Object):void
		{
			// no validation
		}
		
		override protected function fill(data:Object):void
		{
			if (data.hasOwnProperty(JSON_PROPERTY_TURNS)) 						_turns 						= uint(data[JSON_PROPERTY_TURNS]);
			if (data.hasOwnProperty(JSON_PROPERTY_DECK_SIZE))					_deckSize					= uint(data[JSON_PROPERTY_DECK_SIZE]);
			if (data.hasOwnProperty(JSON_PROPERTY_HAND_SIZE))					_handSize					= uint(data[JSON_PROPERTY_HAND_SIZE]);
			if (data.hasOwnProperty(JSON_PROPERTY_DISCARD_SIZE))				_discardSize				= uint(data[JSON_PROPERTY_DISCARD_SIZE]);
			if (data.hasOwnProperty(JSON_PROPERTY_TIMEOUT_ENABLED))				_timeoutEnabled				= Boolean(data[JSON_PROPERTY_TIMEOUT_ENABLED]);
			if (data.hasOwnProperty(JSON_PROPERTY_TIMEOUT_SUBSTITUTION_PHASE))	_timeoutSubstitutionPhase	= uint(data[JSON_PROPERTY_TIMEOUT_SUBSTITUTION_PHASE]);
			if (data.hasOwnProperty(JSON_PROPERTY_TIMEOUT_DISCARD_PHASE))		_timeoutDiscardPhase		= uint(data[JSON_PROPERTY_TIMEOUT_DISCARD_PHASE]);
			if (data.hasOwnProperty(JSON_PROPERTY_TIMEOUT_PLAY_PHASE))			_timeoutPlayPhase			= uint(data[JSON_PROPERTY_TIMEOUT_PLAY_PHASE]);
		}
		
		// -------------------------------------------------------------------------------
		// PUBLIC METHODS
		// -------------------------------------------------------------------------------
		
		public function getGamePhaseTimeout(phase:GamePhase):uint
		{
			// no timeout
			var timeout:uint = 0;
			if (phase.active)
			{
				switch(phase)
				{
					case GamePhase.PLAY:		timeout	= _timeoutPlayPhase; break;
					case GamePhase.DISCARD:		timeout	= _timeoutDiscardPhase; break;
					case GamePhase.SUBSTITUTE:	timeout	= _timeoutSubstitutionPhase; break;
				}
			}
			return timeout;
		}
		
		public function equals(gameOptions:GameOptions):Boolean
		{
			return	_turns						== gameOptions.turns &&
					_deckSize					== gameOptions.deckSize	&& 
					_handSize					== gameOptions.handSize	&&
					_discardSize				== gameOptions.discardSize &&
					_timeoutEnabled				== gameOptions.timeoutEnabled &&
					_timeoutPlayPhase			== gameOptions.timeoutPlayPhase && 
					_timeoutDiscardPhase		== gameOptions.timeoutDiscardPhase &&
					_timeoutSubstitutionPhase	== gameOptions.timeoutSubstitutionPhase;
		}
		
		public function copy(gameOptions:GameOptions):void
		{
			_turns						= gameOptions.turns;
			_deckSize					= gameOptions.deckSize;
			_handSize					= gameOptions.handSize;
			_discardSize				= gameOptions.discardSize;
			_timeoutEnabled				= gameOptions.timeoutEnabled;
			_timeoutPlayPhase			= gameOptions.timeoutPlayPhase;
			_timeoutDiscardPhase		= gameOptions.timeoutDiscardPhase;
			_timeoutSubstitutionPhase	= gameOptions.timeoutSubstitutionPhase;
		}
		
		public function clone():GameOptions
		{
			var options:GameOptions = new GameOptions();
			options.copy(this);
			return options;
		}	
		
		override public function clear():void
		{
			_turns						= DEFAULT_TURNS;
			_deckSize					= DEFAULT_DECK_SIZE;
			_handSize					= DEFAULT_HAND_SIZE;
			_discardSize				= DEFAULT_DISCARD_SIZE;
			_timeoutEnabled				= DEFAULT_TIMEOUT_ENABLED;
			_timeoutPlayPhase			= DEFAULT_TIMEOUT_PLAY_PHASE;
			_timeoutDiscardPhase		= DEFAULT_TIMEOUT_DISCARD_PHASE;
			_timeoutSubstitutionPhase	= DEFAULT_TIMEOUT_SUBSTITUTION_PHASE;
		}
		
		public function dump(source:Array = null, indentDepth:int = 0):Array
		{
			return Dumper.dump(this, null, source, indentDepth);
		}


	}
}